#include <stdio.h>
#include <unistd.h>
#include <linux/input.h>
#include <strings.h>
#include <fcntl.h>

#include "../../include/ts.h"

#define UPAREA(x, y)    ((x)>=100)&&((x)<=200)&&((y)>=280)&&((y)<=380)
#define DOWNAREA(x, y)  (((x)>=100)&&((x)<=200)&&((y)>380)) 
#define LEFTAREA(x, y)  (((x)<100) && ((y)>380))
#define RIGHTAREA(x, y) (((x)<300)&&((x)>200)&&((y)>380))
#define ENTERAREA(x, y) (((x)<100) && ((y)<100))
#define ESCAREA(x, y)   (((x)>700) && ((y)<100))
#define AAREA(x, y)     (((x)>=600)&&((x)<=700)&&((y)>=280)&&((y)<=380))
#define SAREA(x, y)     (((x)>700)&&((y)>=280)&&((y)<=380))
#define ZAREA(x, y)     (((x)>=600)&&((x)<=700)&&((y)>380))
#define XAREA(x, y)     (((x)>700)&&((y)>380))
#define SUPERAREA(x ,y) (((x)>=300)&&((x)<=600)&&((y)<150))

#define KEY_IOCTL_BASE 'x'
#define KEY_IOCTL_UP    _IOW(KEY_IOCTL_BASE,  0, unsigned long) 
#define KEY_IOCTL_DOWN  _IOW(KEY_IOCTL_BASE,  1, unsigned long) 
#define KEY_IOCTL_LEFT  _IOW(KEY_IOCTL_BASE,  2, unsigned long) 
#define KEY_IOCTL_RIGHT _IOW(KEY_IOCTL_BASE,  3, unsigned long) 
#define KEY_IOCTL_A 	_IOW(KEY_IOCTL_BASE,  4, unsigned long) 
#define KEY_IOCTL_S 	_IOW(KEY_IOCTL_BASE,  5, unsigned long) 
#define KEY_IOCTL_Z 	_IOW(KEY_IOCTL_BASE,  6, unsigned long) 
#define KEY_IOCTL_X		_IOW(KEY_IOCTL_BASE,  7, unsigned long) 
#define KEY_IOCTL_ENTER	_IOW(KEY_IOCTL_BASE,  8, unsigned long) 
#define KEY_IOCTL_ESC	_IOW(KEY_IOCTL_BASE,  9, unsigned long) 
#define KEY_IOCTL_SUPER	_IOW(KEY_IOCTL_BASE, 10, unsigned long) 

struct 
{
	bool up;
	bool down;
	bool left;
	bool right;
	bool a;
	bool s;
	bool z;
	bool x;
	bool enter;
	bool esc;
	bool super;
}key_status = {false, false, false, false, false,false, 
			   		false, false, false, false, false};

void ts_trace(int ts, struct coordinate *coor, bool *released)
{
	struct input_event buf;
	*released = false;
	bool x_ready = false;
	bool y_ready = false;

	while(1)
	{
		bzero(&buf, sizeof(buf));
		read(ts, &buf, sizeof(buf));

		if(buf.type == EV_ABS &&
		   buf.code == ABS_PRESSURE &&
		   buf.value == 0)
		{
			*released = true;
			break;
		}

		if(buf.type == EV_ABS &&
		   buf.code == ABS_X)
		{
			coor->x = buf.value;
			x_ready = true;
		}

		if(buf.type == EV_ABS &&
		   buf.code == ABS_Y)
		{
			coor->y = buf.value;
			y_ready = true;
		}

		if(x_ready && y_ready)
			break;
	}
}

void set_key(int fd, int x, int y, unsigned int value)
{
	if (UPAREA(x, y))
	{
		if ((key_status.up && !value) || (!key_status.up && value))
			ioctl(fd, KEY_IOCTL_UP, value);
        if (value)
        	key_status.up = true;
        else
        	key_status.up = false;
	}
    if (DOWNAREA(x, y))
    {
		if ((key_status.down && !value) || (!key_status.down && value))
			ioctl(fd, KEY_IOCTL_DOWN, value);
        if (value)
        	key_status.down = true;
        else
        	key_status.down = false;
	}
    if (LEFTAREA(x, y))
    {
		if ((key_status.left && !value) || (!key_status.left && value))
			ioctl(fd, KEY_IOCTL_LEFT, value);
        if (value)
        	key_status.left = true;
        else
        	key_status.left = false;
	}
    if (RIGHTAREA(x, y))
    {
		if ((key_status.right && !value) || (!key_status.right && value))
			ioctl(fd, KEY_IOCTL_RIGHT, value);
        if (value)
        	key_status.right = true;
        else
        	key_status.right = false;
	}

    if (AAREA(x, y))
    {
		if ((key_status.a && !value) || (!key_status.a && value))
			ioctl(fd, KEY_IOCTL_A, value);
        if (value)
        	key_status.a = true;
        else
        	key_status.a = false;
	}
    if (SAREA(x, y))
    {
		if ((key_status.s && !value) || (!key_status.s && value))
			ioctl(fd, KEY_IOCTL_S, value);
        if (value)
        	key_status.s = true;
        else
        	key_status.s = false;
	}
    if (ZAREA(x, y))
    {
		if ((key_status.z && !value) || (!key_status.z && value))
			ioctl(fd, KEY_IOCTL_Z, value);
        if (value)
        	key_status.z = true;
        else
        	key_status.z = false;
	}
    if (XAREA(x, y))
    {
		if ((key_status.x && !value) || (!key_status.x && value))
			ioctl(fd, KEY_IOCTL_X, value);
        if (value)
        	key_status.x = true;
        else
        	key_status.x = false;
	}

    if (ENTERAREA(x, y))
    {
		if ((key_status.enter && !value) || (!key_status.enter && value))
			ioctl(fd, KEY_IOCTL_ENTER, value);
        if (value)
        	key_status.enter = true;
        else
        	key_status.enter = false;
	}
    if (ESCAREA(x, y))
    {
		if ((key_status.esc && !value) || (!key_status.esc && value))
			ioctl(fd, KEY_IOCTL_ESC, value);
        if (value)
        	key_status.esc = true;
        else
        	key_status.esc = false;
	}

    if (SUPERAREA(x, y))
    {
		if (key_status.up && !value)
			ioctl(fd, KEY_IOCTL_SUPER, value);
        if (value)
        	key_status.up = true;
        else
        	key_status.up = false;
	} 
}

int main()
{	
	int touch_fd = open("/dev/event0", O_RDWR);		
	if (touch_fd < 0)
	{
		perror("touch screen open failed");
		return -1;
	}

	int key_fd	 = open("/dev/key_drv", O_RDWR);
	if (key_fd < 0)
	{
		perror("key character device open failed");
		return -1;
	}

	struct coordinate coor;
	struct coordinate old_coor;
	bool released;
	
	while(1)
	{
		ts_trace(touch_fd, &coor, &released);
		if (released)
			set_key(key_fd, old_coor.x, old_coor.y, 0);
		else
			set_key(key_fd, coor.x, coor.y, 1);
		old_coor = coor;
	}
}